package com.netnovelstore.service.impl;

import com.netnovelstore.dao.BookMapper;
import com.netnovelstore.pojo.Book;
import com.netnovelstore.pojo.BookContent;
import com.netnovelstore.pojo.Exception.FailureBehaviorException;
import com.netnovelstore.pojo.Exception.NotDataException;
import com.netnovelstore.pojo.Result;
import com.netnovelstore.service.AsyncService;
import com.netnovelstore.service.BookService;
import com.netnovelstore.util.FileManager;
import com.netnovelstore.util.Resolver;
import com.netnovelstore.viewObject.BookListResult;
import com.netnovelstore.viewObject.ReadBookResult;
import com.netnovelstore.viewObject.UploadBookFileResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;

@Service
@Slf4j
public class BookServiceImpl implements BookService {


    private BookMapper bookMapper;

    private FileManager fileManager;


    private AsyncService asyncService;

    @Autowired
    public BookServiceImpl(BookMapper bookMapper, FileManager fileManager, AsyncService asyncService) {
        this.bookMapper = bookMapper;
        this.fileManager = fileManager;
        this.asyncService = asyncService;
    }

    @Override
    public Result<Integer> countBookList() {
        Integer count = bookMapper.countBookList();
        log.info("count => " + count);
        Result result = Result.ok(count);
        return result;
    }

    public Integer countBookListByFull() {
        return bookMapper.getCountBySearchBookByFull();
    }

    public Integer countBookListByFree() {
        return bookMapper.getCountBySearchBookByFree();
    }

    @Override
    public Result<List<Book>> getBookList(Integer currentPage, Integer pageSize) throws Exception {
        int pageStart = (currentPage - 1) * pageSize;
        log.info(String.format("[ALL]  ->   从%d 开始查", pageStart));
        List<Book> books = bookMapper.getBookList(pageStart, pageSize);
        if (books == null) {
            throw new Exception("books is null");
        }
        Result<List<Book>> result = Result.ok(books);
        return result;
    }


    @Override
    public Result<ReadBookResult> readBook(Integer bookNumber, Integer number) {
        BookContent bookContent = bookMapper.selectBookByBookContent(bookNumber, number);
        Result result = Result.ok(bookContent.getBookContent());
        return result;
    }

    @Override
    public Result<Integer> getChapterTotal(Integer bookNumber) {
        Integer total = bookMapper.getPathByBookNumber(bookNumber);
        Result result = Result.ok(total);

        return result;
    }

    @Override
    public Result<List<Book>> searchBook(String keyword, Integer currentPage, Integer pageSize) {
        int pageStart = (currentPage - 1) * pageSize;

        log.info(String.format("[%s]  ->  从%d 开始查", keyword, pageStart));
        List<Book> books = bookMapper.searchBook(keyword, pageStart, pageSize);
        if (books == null || books.isEmpty()) {
            throw new NullPointerException("search result is null");
        }
        Result result = Result.ok(books);
        return result;
    }

    @Override
    public Result<List<Book>> getBookListByType(Integer currentPage, Integer pageSize, String type) throws NotDataException {
        int pageStart = (currentPage - 1) * pageSize;

        log.info(String.format("[%s]  ->  从%d 开始查", type, pageStart));
        List<Book> books = bookMapper.getBookListByType(pageStart, pageSize, type);
        if (books == null) {
            throw new NotDataException("books is null");
        }
        Result result = Result.ok(books);
        return result;
    }

    @Override
    public Result<Integer> getCountBySearchBookByType(String type) throws Exception {
        Integer result = bookMapper.getCountBySearchBookByType(type);
        log.info(String.valueOf(result));
        if (result == null) {
            throw new Exception("result is null");
        }
        return Result.ok(result);
    }

    @Override
    public Result<Integer> getCountBySearchBook(String keyword) throws Exception {
        Integer result = bookMapper.getCountBySearchBook(keyword);
        if (result == null) {
            throw new Exception("result is null");
        }
        return Result.ok(result);
    }

    @Override
    public Result<BookListResult> getBookListByFree(Integer currentPage, Integer pageSize) throws NotDataException {
        int pageStart = (currentPage - 1) * pageSize;

        log.info(String.format("[Free]  ->  从%d 开始查", pageStart));
        List<Book> books = bookMapper.getBookListByFree(pageStart, pageSize);
        Integer total = this.countBookListByFree();
        if (books == null) {
            throw new NotDataException("books is null");
        }
        BookListResult bookListResult = new BookListResult();
        bookListResult.setBooks(books);
        bookListResult.setTotal(total);

        Result<BookListResult> result = Result.ok();
        result.setObjects(bookListResult);
        return result;
    }

    @Override
    public Result<BookListResult> getBookListByFull(Integer currentPage, Integer pageSize) throws NotDataException {
        int pageStart = (currentPage - 1) * pageSize;

        log.info(String.format("[Full]  ->  从%d 开始查", pageStart));
        List<Book> books = bookMapper.getBookListByFull(pageStart, pageSize);
        Integer total = this.countBookListByFull();
        if (books == null) {
            throw new NotDataException("books is null");
        }
        BookListResult bookListResult = new BookListResult();
        bookListResult.setBooks(books);
        bookListResult.setTotal(total);

        Result<BookListResult> result = Result.ok();
        result.setObjects(bookListResult);
        return result;
    }


    @Override
    public Result<List<Book>> getBookListByNew(Integer currentPage, Integer pageSize) throws NotDataException {
        int pageStart = (currentPage - 1) * pageSize;

        log.info(String.format("[New]  ->  从%d 开始查", pageStart));
        List<Book> books = bookMapper.getBookListByNew(pageStart, pageSize);
        if (books == null) {
            throw new NotDataException("books is null");
        }
        return Result.ok(books);
    }

    @Override
    public Result<List<Book>> getBookListByHot(Integer currentPage, Integer pageSize) throws NotDataException {
        int pageStart = (currentPage - 1) * pageSize;

        log.info(String.format("[Hot]  ->  从%d 开始查", pageStart));
        log.info(String.format("[Hot]  ->  到%d ", pageStart + pageSize));
        List<Book> books = bookMapper.getBookListByHot(pageStart, pageSize);
        if (books == null) {
            throw new NotDataException("books is null");
        }
        return Result.ok(books);
    }


    @Override
    public Result<Boolean> addBook(Book book) throws Exception {
        log.info("[add book] >>> " + book);
        Boolean to_tb_novel = bookMapper.insertBookTo_tb_novel(book);
        Boolean to_tb_novel_attribute = bookMapper.insertBookTo_tb_novel_attribute(book);

        Integer bookNumber = bookMapper.getBookNumberByBookName(book.getBookName());

        CountDownLatch countDownLatch = new CountDownLatch(1);
        asyncService.asyncBatchInsertBookContent(countDownLatch, bookNumber, book.getBookPath());
        countDownLatch.await();
        return Result.ok(true);

    }


    @Override
    public Result<Boolean> setBookByNumber(Book book) {
        Boolean to_tb_novel = bookMapper.updateBookByNumberTo_tb_novel(book);
        Boolean to_tb_novel_attribute = bookMapper.updateBookByNumberTo_tb_novel_attribute(book);
        return Result.ok(true);
    }

    @Override
    public Result<Boolean> delBooksByNumberList(List<Integer> numberList) throws FailureBehaviorException {
        log.info("[delete book list]=> " + numberList);
        Boolean result = bookMapper.deleteBooksByNumberList(numberList);
        if (!result)
            throw new FailureBehaviorException("deleteBook");
        return Result.ok(true);
    }

    @Override
    public Result<Boolean> setQuantityByNumber(Integer quantity, Integer bookNumber) throws FailureBehaviorException {
        Boolean result = bookMapper.updateQuantityByBookNumber(quantity, bookNumber);
        if (!result)
            throw new FailureBehaviorException("deleteBook");
        return Result.ok();
    }

    @Override
    public Result<UploadBookFileResult> uploadBookFile(MultipartFile file) throws IOException {
        String writeFile = fileManager.writeFile(fileManager.getParentsFolderBookPath(), file);
        log.info("[writeBookFile] = > " + writeFile);
        return Result.ok(writeFile);
    }

    @Override
    public Result<String> uploadBookCover(MultipartFile file) throws IOException {
        String writeFile = fileManager.writeFile(fileManager.getParentsFolderCoversPath(), file);
        log.info("[uploadBookCover] = > " + writeFile);
        Result<String> result = Result.ok();
        result.setObjects("covers/" + writeFile);
        return result;
    }
}
